package deploy

import (
	"bytes"
	"encoding/json"
	"errors"
	"io"
	"os"
	"os/exec"
	"strings"
	"time"
)

// 部署依赖git，project
// project需要galaxy的ssh设置：USERNAME
// 所有服务器之间建立免密登录
// 部署机器上建立构建环境->或者实现docker进行构建

func recoverProject(projectId int) {
	_, _ = ProjectModel.PK(projectId).Update(map[string]interface{}{
		"status": 1,
	})
}

func updateRecord(record *ProjectRecord, process Process, result string, finish bool) error {
	var finishTime *time.Time
	if finish {
		now := time.Now()
		finishTime = &now
	}
	info := map[string]interface{}{
		"process":     process,
		"result":      result + "\n",
		"finish_time": finishTime,
	}
	if finish {
		// 保存结果记录，用于recovery
		//flowB, _ := json.Marshal(record.Flows)
		info["flows"] = record.Flows
	}
	_, err := ProjectRecordModel.PK(record.Id).Update(info)
	if finish {
		data := map[string]interface{}{
			"last_time": finishTime,
		}
		if process == Success {
			data["last_success_time"] = finishTime
		}
		if _, err := ModuleEnvironmentModel.Query().Where("=", "module_id", record.ModuleId).Where("=", "environment_id", record.EnvironmentId).Update(data); err != nil {
			return err
		}
	}
	return err
}

func checkCommandExists(command string) error {
	_, err := exec.LookPath(command)
	if err != nil {
		return errors.New("didn't find " + command + " executable")
	}
	return nil
}
func execCommand(dir string, env []string, updateFn func(r string, finish bool), command string, args ...string) error {
	command = command + " " + strings.Join(args, " ") + "\n"
	result := command + "\n"
	updateFn(result, false)
	cmd := exec.Command("bash", "-c", command)
	cmd.Dir = dir
	var stdoutBuf, stderrBuf bytes.Buffer
	stdout := io.MultiWriter(os.Stdout, &stdoutBuf)
	stderr := io.MultiWriter(os.Stderr, &stderrBuf)
	cmd.Stdout = stdout
	cmd.Stderr = stderr

	additionalEnv := "GALAXY=deploy"
	newEnv := append(os.Environ(), additionalEnv)
	newEnv = append(newEnv, env...)
	cmd.Env = newEnv

	if err := cmd.Start(); err != nil {
		return err
	}
	stop := false
	wait := make(chan struct{}, 1)
	//waitout := make(chan struct{})
	//waiterr := make(chan struct{})
	go func() {
		ticker := time.NewTicker(2 * time.Second)
		for _ = range ticker.C {
			updateFn(stdoutBuf.String(), stop)
			stdoutBuf.Reset()

			updateFn(stderrBuf.String(), stop)
			stderrBuf.Reset()
			if stop {
				break
			}
		}
		ticker.Stop()
		wait <- struct{}{}
	}()
	err := cmd.Wait()
	stop = true
	<-wait
	if err != nil {
		return err
	}
	return nil
}

func generateDcFile(filename string) error {
	result := make(map[string]interface{})
	list := []string{}
	var dcList []DataCenter
	if _, err := DataCenterModel.Query().Find(&dcList); err != nil {
		return err
	}
	for _, dc := range dcList {
		list = append(list, dc.Identity)
		result[dc.Identity] = dc
	}
	result["list"] = list
	resultString, err := json.Marshal(result)
	if err != nil {
		return err
	}
	if f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0755); err != nil {
		return err
	} else {
		defer f.Close()
		if _, err := f.Write(resultString); err != nil {
			return err
		}
	}
	return nil
}
